home *** CD-ROM | disk | FTP | other *** search
- // struct.cpp - data structure display application sample code
- //
- // This is a part of the MetaKit library.
- // Copyright (c) 1996 Meta Four Software.
- // All rights reserved.
- /////////////////////////////////////////////////////////////////////////////
- //
- // This command-line utility displays the data structure of a datafile
- // created with the MetaKit library: as a one-line description (-d), as
- // a terse description without property names (-t), as a graph tree of
- // columns (-c, advanced option), or as a graph tree of fields (default).
- //
- /////////////////////////////////////////////////////////////////////////////
-
- #include "m4kit.h"
- #include "k4field.h"
- #include "k4table.h"
-
- #include <stdio.h>
- #include <string.h>
-
- #if defined (macintosh)
- #include /**/ <console.h>
- #define d4_InitMain(c,v) c = ccommand(&v)
- #endif
-
- #ifdef _MFC_VER
- #define c4_WordArray CWordArray
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // This class generates a string with a pretty tree structure map.
-
- class CStructureMap
- {
- public:
- CStructureMap ();
-
- bool AddNode(int level_, const char* name_,
- int first_ =0, int count_ =0, char enhance_ =0);
-
- const c4_String& Result() const { return _result; }
-
- private:
- c4_WordArray _nextVec;
- c4_WordArray _limitVec;
- c4_String _result;
- };
-
- /////////////////////////////////////////////////////////////////////////////
- // CStructureMap
-
- CStructureMap::CStructureMap ()
- {
- }
-
- //@todo does not yet work if repeating/compound field has depth > 0
-
- bool CStructureMap::AddNode(int level_, const char* name_,
- int first_, int count_, char enhance_)
- {
- int n = _nextVec.GetSize();
- if (level_ >= n)
- {
- _nextVec.Add((unsigned short) first_);
- _limitVec.Add((unsigned short) (first_ + count_));
- ++n;
- }
-
- c4_String s, t;
-
- for (int i = 0; i < n; ++i)
- {
- bool more = _nextVec.GetAt(i) < _limitVec.GetAt(i);
-
- if (i < n - 1 || (more && (int) _nextVec.GetAt(i) > first_))
- {
- if (i == level_ - 1)
- {
- int v = (int) _nextVec.ElementAt(i)++;
- // this uses a silly int to string conversion ...
- s += c4_String (v < 10 ? ' ' : '0' + v / 10)
- + c4_String ('0' + v % 10) + "+-";
- }
- else
- s += i < level_ - 1 ? more ? " | " : " "
- : more ? "--|-" : "----";
- }
-
- t += _nextVec.GetAt(i) < _limitVec.GetAt(i) ? " | " : " ";
- }
-
- _result += ((s + " ") + name_) + "\n";
-
- if (enhance_)
- {
- s = t.Left(t.GetLength() - 4) + " ";
-
- int i = strlen(name_);
- if (i < 2)
- i = 2;
-
- while (--i >= 0)
- s += enhance_;
-
- _result += s + "\n";
- }
-
- _result += t + "\n";
-
- while (n > 0 && _nextVec.GetAt(n-1) >= _limitVec.GetAt(n-1))
- --n;
-
- _nextVec.SetSize(n);
- _limitVec.SetSize(n);
-
- return n > 0;
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- static c4_String DisplayFieldStructure(const c4_Field& field_)
- {
- CStructureMap map;
-
- const c4_Field* f = &field_;
- do
- {
- if (f->NumSubFields() > 0)
- {
- if (f->IsRepeating())
- {
- map.AddNode(f->Level(), f->Name(), 1, f->NumSubFields() - 1, '=');
-
- if (f->NumSubFields() > 1)
- {
- f = & f->SubField(1);
- continue;
- }
- }
- else
- {
- map.AddNode(f->Level(), f->Name(), 0, f->NumSubFields(), '-');
-
- f = & f->SubField(0);
- continue;
- }
- }
- else
- map.AddNode(f->Level(), f->Name());
-
- while (!f->IsRoot())
- {
- c4_Field& parent = f->Parent();
-
- if (f->Index() < parent.NumSubFields() - 1)
- {
- f = & parent.SubField(f->Index() + 1);
- break;
- }
-
- f = & parent;
- }
-
- } while (!f->IsRoot());
-
- return map.Result();
- }
-
- static c4_String DisplayTableStructure(const c4_Field& field_)
- {
- CStructureMap map;
-
- const c4_Field* f = &field_;
- do
- {
- if (f->NumSubFields() > 0)
- {
- if (f->IsRepeating())
- {
- map.AddNode(f->SubField(0).Degree(), f->Name(),
- 0, f->NumSubColumns(), '=');
- if (f->NumSubFields() > 1)
- {
- f = & f->SubField(1);
- continue;
- }
- }
- else
- {
- f = & f->SubField(0);
- continue;
- }
- }
- else if (f->Width() > 0)
- map.AddNode(f->Degree(), f->Name());
-
- while (!f->IsRoot())
- {
- c4_Field& parent = f->Parent();
-
- if (f->Index() < parent.NumSubFields() - 1)
- {
- f = & parent.SubField(f->Index() + 1);
- break;
- }
-
- f = & parent;
- }
-
- } while (!f->IsRoot());
-
- return map.Result();
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- #ifdef _DEBUG
-
- void TestStructureMap()
- {
- static struct c_Info { int level, count; const char* name; } info [] =
- {
- 0, 1, "root",
- 1, 6, "doc",
- 2, 3, "naw",
- 3, 2, "n",
- 4, -1, "vn",
- 2, -1, "x",
- 4, -1, "an",
- 3, -1, "a",
- 3, -1, "w",
- 2, 2, "tel",
- 3, -1, "n",
- 3, -1, "t",
- 2, 2, "structure",
- 3, -1, "a",
- 3, -1, "b",
- 2, 0, "aux",
- 2, 1, "extra",
- 3, -1, "hot",
- 0, 0, 0
- };
-
- c4_StructureMap map;
-
- for (c_Info* p = info; p->name; ++p)
- if (p->count >= 0)
- map.AddNode(p->level, p->name, 1, p->count, '=');
- else
- map.AddNode(p->level, p->name);
-
- puts(map.Result());
- }
-
- /* Output should be:
-
- root
- ====
- |
- 1+- doc
- ===
- |
- 1+- naw
- | ===
- | |
- | 1+- n
- | | ==
- | | |
- | | 1+- vn
- | | |
- 2+---|---|- x
- | | |
- | | 2+- an
- | |
- | 2+- a
- | |
- | 3+- w
- |
- 3+- tel
- | ===
- | |
- | 1+- n
- | |
- | 2+- t
- |
- 4+- structure
- | =========
- | |
- | 1+- a
- | |
- | 2+- b
- |
- 5+- aux
- | ===
- |
- 6+- extra
- =====
- |
- 1+- hot
- */
-
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
-
- /*! 960228: doesn't work, linker complains about mult-def, even with /NOE ???
- // this stub prevents loading all handlers, which are not needed here
- c4_Handler* f4_CreateHandler(char)
- {
- return 0;
- }
- */
-
- int main(int argc, char** argv)
- {
- #ifdef d4_InitMain
- d4_InitMain(argc, argv);
- #endif
-
- char option = 0;
-
- // check for a leading option and take it off
- if (argc > 1 && (*argv[1] == '-' || *argv[1] == '/'))
- {
- option = argv[1][1];
- --argc;
- ++argv;
- }
-
- // the debug version tests CStructureMap if no filename is specified
- if (argc != 2)
- {
- #ifdef _DEBUG
- TestStructureMap();
- #else
- fputs("Usage: STRUCT [-d|-t|-c] datafile", stderr);
- #endif
-
- return 1;
- }
-
- // open the storage to obtain its structure definition
- c4_Storage store (argv[1], false);
- c4_Field& def = store.RootTable().Definition();
-
- // display the field structure in one of several formats
- c4_String s;
- switch (option)
- {
- case 'd': case 'D': s = def.Description(); break;
- case 't': case 'T': s = def.Description(true); break;
- case 'c': case 'C': s = DisplayTableStructure(def); break;
- default: s = DisplayFieldStructure(def);
- }
- puts(s);
-
- return 0;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // $Id: struct.cpp,v 1.5 1996/12/06 23:39:31 jcw Exp $
-